#pragma once
#include <iostream>
#include <string>
#include <assert.h>
#include <jsoncpp/json/json.h>

#include "Log.hpp"

#define CRLF "\r\n"
#define CRLF_LEN strlen(CRLF)
#define SPACE " "
#define SPACE_LEN strlen(SPACE)
#define OPS "+-*/%"

// encode,对整个序列化之后的字符串进行添加长度
//"strlen\r\nXXXXXX\r\n"
std::string encode(std::string &in, uint32_t len)
{
    // "exitCode_ result_"
    // "len\r\n" "exitCode_ result_\r\n"
    std::string encodeStr = std::to_string(len);
    encodeStr += CRLF;
    encodeStr += in;
    encodeStr += CRLF;

    //std::cout << "debug->encode-> " << encodeStr << std::endl;
    return encodeStr;
}

// decode，整个序列化之后的字符串进 行提取长度
// 1. 必须具有完整的长度
// 2. 必须具有和len相符合的有效载荷
// 我们才返回有效载荷和len
// 否则，我们就是一个检测函数！
// 9\r\n100 + 200\r\n    9\r\n112 / 200\r\n
std::string decode(std::string &in, uint32_t *len)
{
    assert(len);

    // 1. 确认是否是一个包含len的有效字符串
    *len = 0;
    size_t pos = in.find(CRLF);
    if(pos == std::string::npos)
        return "";

    // 2. 提取长度
    std::string strLen = in.substr(0, pos);
    int intLen = atoi(strLen.c_str());

    // 3. 确认有效载荷也是符合要求的
    int surplus = in.size() - 2 * CRLF_LEN - pos;
    if(surplus < intLen)
    {
        return "";
    }

    // 4. 确认有完整的报文结构
    std::string package = in.substr(pos + CRLF_LEN, intLen);
    *len = intLen;

    // 5. 将当前报文完整的从in中全部移除掉
    int remLen = strLen.size() + 2 *CRLF_LEN + package.size();
    in.erase(0, remLen);

    // 6. 正常返回
    return package;
}


// 定制请求 
class Request
{
public:
    Request()
    {}
    
    ~Request()
    {}

    int& getX()
    { return x_;}

    int& getY()
    { return y_;}
    
    char& getOp()
    { return op_;}

    // 序列化
    void serialization(std::string *out)
    {
#ifdef MY_SELF
        // 100 + 200 
        // "100 + 200"
        std::string dateOne = std::to_string(x_);
        std::string dateTwo = std::to_string(y_);
        std::string dateOp = std::to_string(op_);

        *out = dateOne;
        *out += SPACE;
        //*out += dateOp;
        *out += op_;
        *out += SPACE;
        *out += dateTwo;
        //std::cout << *out << std::endl;
#else
        //
        Json::Value root;  //，万能对象，任意类型
        root["x"] = x_;
        root["y"] = y_;
        root["op"] = op_;

        Json::StyledWriter fw;
        //Json::FastWriter fw;
        *out = fw.write(root);
#endif
    }

    // 反序列化
    bool deserialization(std::string &in)
    {
#ifdef MY_SELF
        //std::cout << 0 << std::endl;
        // 100 + 200 
        size_t spaceOne = in.find(SPACE);
        if(spaceOne == std::string::npos) return false;
        //std::cout << 1 << std::endl;

        size_t spaceTwo = in.rfind(SPACE);
        if(spaceTwo == std::string::npos) return false;
        //std::cout << 2 << std::endl;

        std::string dateOne = in.substr(0, spaceOne);
        std::string dateTwo = in.substr(spaceTwo + SPACE_LEN);
        std::string dateOp = in.substr(spaceOne + SPACE_LEN, spaceTwo - (spaceOne + SPACE_LEN));
        if(dateOp.size() != 1) 
        {
            printf("%d:%c\n", dateOp.size(), dateOp.c_str());
            return false;
        }
        //std::cout << 3 << std::endl;

        // 转成内部成员
        x_ = atoi(dateOne.c_str());
        y_ = atoi(dateTwo.c_str());
        op_ = dateOp[0];

        return true;
#else
    Json::Value root;
    Json::Reader rd;
    rd.parse(in, root);

    x_ = root["x"].asInt();
    y_ = root["y"].asInt();
    op_ = root["op"].asInt();

    return true;
#endif
    }

    void debug()
    {
        std::cout << "x_" << x_ << std::endl;
        std::cout << "y_" << y_ << std::endl;
        std::cout << "op_" << op_ << std::endl;
    }
private:
    // 需要计算的数据
    int x_; 
    int y_;
    // 需要计算的种类,"+ - * / %"
    char op_;
};

// 定制响应
class Response
{
public:
    Response()
    :result_(0)
    ,exitCode_(0)
    {}
    
    ~Response()
    {}

    // 序列化
    void serialization(std::string *out)
    {
#ifdef MY_SELF

        // "exitCode_ result_"

        std::string ec = std::to_string(exitCode_);
        std::string res = std::to_string(result_);

        *out = ec;
        *out += SPACE;
        *out += res;
#else
    Json::Value root;
    root["exitCode"] = exitCode_;
    root["result"] = result_;

    Json::FastWriter fw;
    *out = fw.write(root);
#endif
    }

    // 反序列化
    bool deserialization(std::string &in)
    {
#ifdef MY_SELF
        // "nextiCode_ result_"
        size_t pos = in.find(SPACE);
        if(pos == std::string::npos) return false;

        std::string ec = in.substr(0, pos);
        std::string res = in.substr(pos + SPACE_LEN);

        exitCode_ = atoi(ec.c_str());
        result_ = atoi(res.c_str());

        return true;
#else
    Json::Value root;
    Json::Reader rd;
    rd.parse(in, root);

    exitCode_ = root["exitCode"].asInt();
    result_ = root["result"].asInt();

    return true;
#endif
    }

public:
    // 退出状态，0标识运算结果合法，非0标识运算结果是非法的
    int exitCode_; 
    // 运算结果
    int result_;
};

bool makeReuquest(const std::string &str, Request *req)
{
    // 123+1  1*1 1/1
    char strtmp[1024];
    snprintf(strtmp, sizeof strtmp, "%s", str.c_str());
    char *left = strtok(strtmp, OPS);
    if (!left)
        return false;
    char *right = strtok(nullptr, OPS);
    if (!right)
        return false;
    char mid = str[strlen(left)];

    req->getX() = atoi(left);
    req->getY() = atoi(right);
    req->getOp() = mid;
    return true;
}